package com.xbongbong.pro.service.market.statistics.impl;

import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.pojo.XbbAggregatedPage;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.saas.domain.entity.StaticForMarketActivityEntity;
import com.xbongbong.saas.domain.entity.StaticForMarketUpdateEntity;
import com.xbongbong.saas.domain.entity.StaticForUpdateDTO;
import com.xbongbong.saas.domain.entity.ext.MarketActivityEntityExt;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.MarketActivityEnum;
import com.xbongbong.saas.model.MarketActivityForStaticModel;
import com.xbongbong.saas.model.MarketActivityModel;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.data.domain.PageRequest;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;

import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * @Auther: yingjianfeng
 * @Date: 2022/3/15 14:42
 * @Description:
 */
@Slf4j
@Service("marketActivity4StaticHandleImpl")
public class MarketActivity4StaticHandleImpl extends AbstractMarketActivity4StaticHandle {
    @Resource
    private MarketActivityForStaticModel marketActivityForStaticModel;
    @Resource
    private MarketActivityModel marketActivityModel;
    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;
    @Resource
    private EsHelper esHelper;

    @Override
    public Integer type() {
        return XbbRefTypeEnum.MARKET_ACTIVITY.getCode();
    }

    @Override
    @Async("staticsMarketData")
    public void add(PaasFormDataEntity paasFormDataEntity) throws XbbException {
        try {
            Long id = paasFormDataEntity.getId();
            String corpid = paasFormDataEntity.getCorpid();
            JSONObject data = paasFormDataEntity.getData();
            StaticForMarketActivityEntity addEntity = new StaticForMarketActivityEntity();
            addEntity.setCorpid(corpid);
            StaticForMarketActivityEntity updateEntity = new StaticForMarketActivityEntity();
            updateEntity.setCorpid(corpid);
            List<StaticForMarketActivityEntity> addEntitys = new ArrayList<>();
            List<StaticForMarketActivityEntity> updateEntitys = new ArrayList<>();
            addEntity.setMarketId(id);
            addEntity.setMarketType(data.getString(MarketActivityEnum.GENRE.getAttr()));
            addEntity.setMarketEndTime(data.getLong(MarketActivityEnum.END_TIME.getAttr()));
            addEntity.setMarketName(data.getString(MarketActivityEnum.NAME.getAttr()));
            addEntity.setActualCost(data.getDouble(MarketActivityEnum.REAL_COST.getAttr()));
            addEntitys.add(addEntity);
            // 插入新数据
            if (CollectionsUtil.isNotEmpty(addEntitys)) {
                marketActivityForStaticModel.insertBatch(addEntitys, corpid);
            }
            if (CollectionsUtil.isNotEmpty(updateEntitys)) {
                marketActivityForStaticModel.updateBatchForStatic(updateEntitys);
            }
        } catch (XbbException e) {
            log.error("com.xbongbong.pro.service.marketActivity4Static.MarketActivity4StaticHandle.add ", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    @Override
    @Async("staticsMarketData")
    public void update(PaasFormDataEntity paasFormDataEntity) throws XbbException {
        try {
            String corpid = paasFormDataEntity.getCorpid();
            JSONObject data = paasFormDataEntity.getData();
            Boolean flag = false;
            List<StaticForMarketUpdateEntity> listEntitys = new ArrayList<>();
            IndexTypeEnum indexTypeEnum = IndexTypeEnum.IDX_STATICS_MARKET_DATA;
            BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
            boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
            boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
            boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, indexTypeEnum.getType()));
            boolQueryBuilder.filter(termQuery("marketId", paasFormDataEntity.getDataId()));
            flag = updateMarket4MarketActivity(corpid, data, flag, indexTypeEnum, listEntitys, boolQueryBuilder, paasFormDataEntity);
            if (flag && CollectionsUtil.isNotEmpty(listEntitys)) {
                // 可能需要改动, listEntitys可能数量有点多
                marketActivityForStaticModel.updateBatch(listEntitys, corpid);
            }
        } catch (XbbException e) {
            log.error("com.xbongbong.pro.service.marketActivity4Static.MarketActivity4StaticHandle.update ", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }

    }

    @Override
    @Async("staticsMarketData")
    public void updateBatch(List<StaticForUpdateDTO> list, String corpid) throws XbbException {
        try {

            String key = null;
            JSONObject data = new JSONObject();
            List<Long> udpateIds = new ArrayList<>();
            Object value = null;
            if (list.size() > 0) {
                key = list.get(0).getData().getString("key");
                data = list.get(0).getData();
                Set<String> strings = data.keySet();
                for (String string : strings) {
                    key = string;
                }
                value = data.get(key);
                list.forEach(item -> {
                    udpateIds.add(item.getId());
                });
            }
            List<StaticForMarketUpdateEntity> listEntitys = new ArrayList<>();
            Boolean flag = false;
            List<String> attrs = new ArrayList<>();
            IndexTypeEnum indexTypeEnum = IndexTypeEnum.IDX_STATICS_MARKET_DATA;
            BoolQueryBuilder boolQueryBuilder = getBaseBoolQueryBuilder(corpid, indexTypeEnum);
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
            attrs = Arrays.asList(MarketActivityEnum.GENRE.getAttr(), MarketActivityEnum.NAME.getAttr(), MarketActivityEnum.END_TIME.getAttr(), MarketActivityEnum.REAL_COST.getAttr());
            if (attrs.contains(key)) {
                boolQueryBuilder.filter(termsQuery("marketId", udpateIds));
                sourceBuilder.query(boolQueryBuilder);
                searchRequest.source(sourceBuilder);
                long count = xbbElasticsearchRestTemplate.count(searchRequest, PaasFormDataEntityExt.class);
                for (int i = 0; i <= count / 100; i++) {
                    PageRequest pageRequest = EsUtil.setPage(sourceBuilder, i + 1, 100);
                    XbbAggregatedPage<StaticForMarketActivityEntity> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, StaticForMarketActivityEntity.class);
                    List<StaticForMarketActivityEntity> content = esEntities.getContent();
                    String finalKey = key;
                    Object finalValue = value;
                    for (StaticForMarketActivityEntity item : content) {
                        StaticForMarketUpdateEntity staticForMarketUpdateEntity = new StaticForMarketUpdateEntity();
                        staticForMarketUpdateEntity.setCorpid(corpid);
                        staticForMarketUpdateEntity.setId(item.getDataId());
                        if (Objects.equals(finalKey, MarketActivityEnum.GENRE.getAttr())) {
                            flag = true;
                            staticForMarketUpdateEntity.setMarketType(finalValue.toString());
                        }
                        if (Objects.equals(finalKey, MarketActivityEnum.NAME.getAttr())) {
                            flag = true;
                            staticForMarketUpdateEntity.setMarketName(finalValue.toString());
                        }
                        if (Objects.equals(finalKey, MarketActivityEnum.END_TIME.getAttr())) {
                            flag = true;
                            if (Objects.nonNull(finalValue)) {
                                staticForMarketUpdateEntity.setMarketEndTime(Long.parseLong(finalValue.toString()));
                            } else {
                                staticForMarketUpdateEntity.setMarketEndTime(null);
                            }
                        }
                        if (Objects.equals(finalKey, MarketActivityEnum.REAL_COST.getAttr())) {
                            flag = true;
                            if (Objects.nonNull(finalValue)) {
                                staticForMarketUpdateEntity.setActualCost(Double.valueOf(finalValue.toString()));
                            } else {
                                staticForMarketUpdateEntity.setActualCost(null);
                            }
                        }
                        listEntitys.add(staticForMarketUpdateEntity);
                    }
                }
            }
            if (flag && CollectionsUtil.isNotEmpty(listEntitys)) {
                // 可能需要改动, listEntitys可能数量有点多
                marketActivityForStaticModel.updateBatch(listEntitys, corpid);
            }
        } catch (XbbException e) {
            log.error("com.xbongbong.pro.service.marketActivity4Static.MarketActivity4StaticHandle.updateBatch ", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    @Override
    @Async("staticsMarketData")
    public void deleteBatch(List<Long> idIn, String corpid, Integer del) throws XbbException {
        try {

            if (idIn.size() == 0) {
                return;
            }
            // 这个优先级最高,必须得最先处理
            List<Long> otherNeedDel = new ArrayList<>();
            List<Long> delIds = new ArrayList<>();
            List<Long> updateIds = new ArrayList<>();
            IndexTypeEnum indexTypeEnum = IndexTypeEnum.IDX_STATICS_MARKET_DATA;
            BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
            boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
            // 这里暂不处理这个del条件
            boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, indexTypeEnum.getType()));
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
            List<StaticForMarketActivityEntity> staticList = new ArrayList<>();
            StaticForMarketActivityEntity staticForMarketActivityEntity = new StaticForMarketActivityEntity();
            long count;
            Boolean flag = false;
            boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
            boolQueryBuilder.filter(termsQuery("marketId", idIn));
            sourceBuilder.query(boolQueryBuilder);
            searchRequest.source(sourceBuilder);
            count = xbbElasticsearchRestTemplate.count(searchRequest, PaasFormDataEntityExt.class);
            getDelIds(delIds, sourceBuilder, searchRequest, count);
            if (otherNeedDel.size() > 0) {
                marketActivityForStaticModel.deleteBatch(otherNeedDel, corpid, DelEnum.DELETE.getDel());
            }
            if (delIds.size() > 0) {
                // 可能需要改动, listEntitys可能数量有点多
                marketActivityForStaticModel.deleteBatch(delIds, corpid, del);
            }
            if (staticList.size() > 0) {
                marketActivityForStaticModel.insertBatch(staticList, corpid);
            }
        } catch (XbbException e) {
            log.error("com.xbongbong.pro.service.marketActivity4Static.MarketActivity4StaticHandle.deleteBatch ", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }
    /**
     * 更新市场活动时是否需要处理中间表
     * date: 2022/3/14 9:44 上午
     *
     * @author yingjf
     */
    private Boolean updateMarket4MarketActivity(String corpid, JSONObject data, Boolean flag, IndexTypeEnum
            indexTypeEnum, List<StaticForMarketUpdateEntity> listEntitys, BoolQueryBuilder
                                                        boolQueryBuilder, PaasFormDataEntity paasFormDataEntity) throws XbbException {
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
        sourceBuilder.query(boolQueryBuilder);
        searchRequest.source(sourceBuilder);
        long count = xbbElasticsearchRestTemplate.count(searchRequest, StaticForMarketActivityEntity.class);
        if (Objects.equals(count, 0L)) {
            StaticForMarketActivityEntity staticForMarketActivityEntity = new StaticForMarketActivityEntity();
            MarketActivityEntityExt byKey = marketActivityModel.getByKey(paasFormDataEntity.getId(), corpid);
            JSONObject data1 = byKey.getData();
            staticForMarketActivityEntity.setMarketId(byKey.getId());
            staticForMarketActivityEntity.setCorpid(corpid);
            staticForMarketActivityEntity.setMarketType(data1.getString(MarketActivityEnum.GENRE.getAttr()));
            staticForMarketActivityEntity.setMarketEndTime(data1.getLong(MarketActivityEnum.END_TIME.getAttr()));
            staticForMarketActivityEntity.setMarketName(data1.getString(MarketActivityEnum.NAME.getAttr()));
            staticForMarketActivityEntity.setActualCost(data1.getDouble(MarketActivityEnum.REAL_COST.getAttr()));
            marketActivityForStaticModel.insert(staticForMarketActivityEntity);
            return false;
        }
        for (int i = 0; i <= count / 100; i++) {
            PageRequest pageRequest = EsUtil.setPage(sourceBuilder, i + 1, 100);
            XbbAggregatedPage<StaticForMarketActivityEntity> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, StaticForMarketActivityEntity.class);
            List<StaticForMarketActivityEntity> content = esEntities.getContent();
            for (StaticForMarketActivityEntity entity : content) {
                StaticForMarketUpdateEntity staticForMarketUpdateEntity = new StaticForMarketUpdateEntity();
                staticForMarketUpdateEntity.setCorpid(corpid);
                if (StringUtil.isNotEmpty(data.getString(MarketActivityEnum.GENRE.getAttr())) && !Objects.equals(entity.getMarketType(), data.getString(MarketActivityEnum.GENRE.getAttr()))) {
                    flag = true;
                    staticForMarketUpdateEntity.setMarketType(data.getString(MarketActivityEnum.GENRE.getAttr()));
                }
                if (StringUtil.isNotEmpty(data.getString(MarketActivityEnum.NAME.getAttr())) && !Objects.equals(entity.getMarketName(), data.getString(MarketActivityEnum.NAME.getAttr()))) {
                    flag = true;
                    staticForMarketUpdateEntity.setMarketName(data.getString(MarketActivityEnum.NAME.getAttr()));
                }
                if (!Objects.equals(entity.getMarketEndTime(), data.getLong(MarketActivityEnum.END_TIME.getAttr()))) {
                    flag = true;
                    staticForMarketUpdateEntity.setMarketEndTime(data.getLong(MarketActivityEnum.END_TIME.getAttr()));
                }
                if (!Objects.equals(entity.getActualCost(), data.getDouble(MarketActivityEnum.REAL_COST.getAttr()))) {
                    flag = true;
                    staticForMarketUpdateEntity.setActualCost(data.getDouble(MarketActivityEnum.REAL_COST.getAttr()));
                }
                if (flag) {
                    staticForMarketUpdateEntity.setId(entity.getDataId());
                    listEntitys.add(staticForMarketUpdateEntity);
                }
            }
        }
        return flag;
    }


}

